import actory,random,factory



class Game(actory.World):
    def __init__(self):
        super(Game,self).__init__()

        self.who_has = "p"
        self.in_cs = 0
        self.shared_resource_is_available = True

    def lock_shared_resource(self, entity):
        self.shared_resource_is_available = False
        self.who_has = entity
        self.in_cs = self.in_cs + 1

    def unlock_shared_resource(self, entity):
        self.shared_resource_is_available = True
        "give away the resource turn"
        if entity == "p": self.who_has = "c"
        if entity == "c": self.who_has = "p"
        self.in_cs = self.in_cs - 1
        

    def avail_cs(self,entity):
        return self.shared_resource_is_available and self.has_the_resource(entity)
    
    def has_the_resource(self, entity):
        return entity == self.who_has

    def deadlock(self):
        return self.in_cs > 1
        
    
def mutual_exclusion_demo():
    "Demo"

    producer = actory.Easy("""
        #p0  |                       |                           |Initial Producer State          | #p1
        #p1  |?avail_cs("p")         |                           |Producer Checks if can go to CS | #pcs*10
             |                       |                           |Producer Waiting                | #p1
        #pcs |                       |?lock_shared_resource("p") |Producer enters Critical Section| #pcs1
        #pcs1|                       |?unlock_shared_resource("p")  |Producer Exits Critical Section | #p0 
    """)
    producer.name = "Producer"

    consumer = actory.Easy("""
        #c0  |                       |                           |Initial Consumer State          | #c1
        #c1  |         |                           |Consumer Checks if can go to CS | #ccs*10
             |                       |                           |Consumer Waiting                | #c1
        #ccs |                       |?lock_shared_resource("c") |Consumer enters Critical Section| #ccs1
        #ccs1|                       |?unlock_shared_resource("c")  |Consumer Exits Critical Section | #c0
    """)
    consumer.name = "Consumer"
    
    ok = actory.Easy("""
       #ok   |?deadlock()            |                           |Deadlock    |_fault
             |                       |                           |No Deadlock |#ok
    """)
    ok.name = "Deadlock Checker"
    
    f = factory.Factory()
    machines = [producer, consumer, ok]
    for i in machines: f.add_machine(i)
    universe = Game()
    f.run(universe, 500)
        
if __name__ == "__main__":
    random.seed()

    "demo of mutual exclusion & deadlock"
    mutual_exclusion_demo()
